﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TipoDatos;

namespace P2P
{
    class cMensajes
    {
        internal static byte[] Login(tProtocol protocol, Byte[] clientID)
        {
            byte[] data = new byte[86];
            data[0] = Convert.ToByte(protocol);  // protocol (1byte): 0xE3 - eDonkey // 0xC5 - eMule

            data[1] = 81; // size (4bytes): mensaje sin contar el header
            data[2] = 0x00;
            data[3] = 0x00;
            data[4] = 0x00;

            data[5] = Convert.ToByte(tOpcode.OP_LOGINREQUEST); // type (1byte): el valor del opcode OP_LOGINREQUEST = 0x01

            data[6] = 0xc1; // user hash (16bytes): formado por números aleatorios menos los bytes 6º y 15º
            data[7] = 0x66;
            data[8] = 0x3c;
            data[9] = 0xc2;
            data[10] = 0x59;
            data[11] = 0x0e; // este byte siempre vale 14
            data[12] = 0x77;
            data[13] = 0xe3;
            data[14] = 0x9f;
            data[15] = 0x9b;
            data[16] = 0x33;
            data[17] = 0x2a;
            data[18] = 0x41;
            data[19] = 0x82;
            data[20] = 0x6f; // este byte siempre vale 111
            data[21] = 0xdf;

            data[22] = clientID[0]; // client ID (4bytes): en la primera conexión puede ser 0
            data[23] = clientID[1];
            data[24] = clientID[2];
            data[25] = clientID[3];
            //data[22] = 0x54; // client ID (4bytes): en la primera conexión puede ser 0 y es un valor único para cada conexión 
            //data[23] = 0x7f;
            //data[24] = 0x08;
            //data[25] = 0x45;

            data[26] = 0xd0; // TCP Port (2bytes): puerto usado por el cliente
            data[27] = 0x5b;

            data[28] = 0x04; // tag count (4bytes): número de etiquetas que contiene el mensaje
            data[29] = 0x00;
            data[30] = 0x00;
            data[31] = 0x00;

            data[32] = 0x02; // name tag (Xbytes): nickname del usuario
            data[33] = 0x01;
            data[34] = 0x00;
            data[35] = 0x01;
            data[36] = 0x18;
            data[37] = 0x00;
            data[38] = 0x68; // nick: http://emule-project.net
            data[39] = 0x74;
            data[40] = 0x74;
            data[41] = 0x70;
            data[42] = 0x3a;
            data[43] = 0x2f;
            data[44] = 0x2f;
            data[45] = 0x65;
            data[46] = 0x6d;
            data[47] = 0x75;
            data[48] = 0x6c;
            data[49] = 0x65;
            data[50] = 0x2d;
            data[51] = 0x70;
            data[52] = 0x72;
            data[53] = 0x6f;
            data[54] = 0x6a;
            data[55] = 0x65;
            data[56] = 0x63;
            data[57] = 0x74;
            data[58] = 0x2e;
            data[59] = 0x6e;
            data[60] = 0x65;
            data[61] = 0x74;

            data[62] = 0x03; // version tag (8bytes)
            data[63] = 0x01;
            data[64] = 0x00;
            data[65] = 0x11;
            data[66] = 0x3c;
            data[67] = 0x00;
            data[68] = 0x00;
            data[69] = 0x00;

            data[70] = 0x03; // port tag (8bytes)
            data[71] = 0x01;
            data[72] = 0x00;
            data[73] = 0x20;
            data[74] = 0x19;
            data[75] = 0x03;
            data[76] = 0x00;
            data[77] = 0x00;

            data[78] = 0x03; // flags tag (8bytes)
            data[79] = 0x01;
            data[80] = 0x00;
            data[81] = 0xfb;
            data[82] = 0x00;
            data[83] = 0xc8;
            data[84] = 0x00;
            data[85] = 0x00;

            return data;
        }

        internal static byte[] GetListServers(tProtocol protocol)
        {
            byte[] data = new byte[86];
            data[0] = Convert.ToByte(protocol);  // protocol (1byte): 0xE3 - eDonkey // 0xC5 - eMule

            data[1] = 0x00; // size (4bytes): mensaje sin contar el header
            data[2] = 0x00;
            data[3] = 0x00;
            data[4] = 0x00;

            data[5] = Convert.ToByte(tOpcode.OP_GETLISTSERVERS); // type (1byte): el valor del opcode OP_SERVERSTATUS = 0x14

            return data;
        }

        internal static byte[] HelloAnswer(tProtocol protocol, Byte[] Login)
        {
            byte[] data = new byte[Login.Length];
            data[0] = Convert.ToByte(protocol);  // protocol (1byte): 0xE3 - eDonkey // 0xC5 - eMule

            data[1] = Convert.ToByte(Login.Length - 5); // size (4bytes): mensaje sin contar el header
            data[2] = 0x00;
            data[3] = 0x00;
            data[4] = 0x00;

            data[5] = Convert.ToByte(tOpcode.OP_HELLOANSWER); // type (1byte): el valor del opcode OP_HELLOANSWER = 0x4C

            for (int i = 6; i < Login.Length; i++)
                data[i] = Login[i];

            return data;
        }

        internal static byte[] Search(tProtocol protocol, string text)
        {
            ASCIIEncoding encode = new ASCIIEncoding();
            Byte[] cad = encode.GetBytes(text);

            Byte[] data = new byte[cad.Length + 9];
            data[0] = Convert.ToByte(protocol);  // protocol (1byte): 0xE3 - eDonkey // 0xC5 - eMule
            data[1] = Convert.ToByte(cad.Length + 4); // size (4bytes): mensaje sin contar el header
            data[2] = 0x00;
            data[3] = 0x00;
            data[4] = 0x00;
            data[5] = 0x16;
            data[6] = 0x01;
            data[7] = Convert.ToByte(cad.Length);
            data[8] = 0x00;

            for (int i = 0; i < cad.Length; i++) // cadena de búsqueda
                data[9 + i] = cad[i];

            return data;
        }

        internal static byte[] Callback(tProtocol protocol, byte[] clientid)
        {
            Byte[] data = new byte[10];
            data[0] = Convert.ToByte(protocol);  // protocol (1byte): 0xE3 - eDonkey // 0xC5 - eMule
            data[1] = 0x04; // size (4bytes): mensaje sin contar el header
            data[2] = 0x00;
            data[3] = 0x00;
            data[4] = 0x00;
            data[5] = 0x1C;
            data[6] = clientid[0];
            data[7] = clientid[1];
            data[8] = clientid[2];
            data[9] = clientid[3];

            return data;
        }

        internal static byte[] GetSources(tProtocol protocol, byte[] hash)
        {
            Byte[] data = new byte[22];
            data[0] = Convert.ToByte(protocol);  // protocol (1byte): 0xE3 - eDonkey // 0xC5 - eMule
            data[1] = 0x11; // size (4bytes): mensaje sin contar el header
            data[2] = 0x00;
            data[3] = 0x00;
            data[4] = 0x00;
            data[5] = 0x19;

            Array.Copy(hash, 0, data, 6, 16);

            return data;
        }

        internal static byte[] GetSources(tProtocol protocol, byte[] hash, byte[] size)
        {
            Byte[] data = new byte[26];
            data[0] = Convert.ToByte(protocol);  // protocol (1byte): 0xE3 - eDonkey // 0xC5 - eMule
            data[1] = 0x15; // size (4bytes): mensaje sin contar el header
            data[2] = 0x00;
            data[3] = 0x00;
            data[4] = 0x00;
            data[5] = 0x58;

            Array.Copy(hash, 0, data, 6, 16);
            Array.Copy(size, 0, data, 22, 4);

            return data;
        }

        internal static byte[] FileRequest(tProtocol protocol, byte[] hash)
        {
            Byte[] data = new byte[22];
            data[0] = Convert.ToByte(protocol);  // protocol (1byte): 0xE3 - eDonkey // 0xC5 - eMule
            data[1] = 0x11; // size (4bytes): mensaje sin contar el header
            data[2] = 0x00;
            data[3] = 0x00;
            data[4] = 0x00;
            data[5] = 0x58;

            Array.Copy(hash, 0, data, 6, 16);

            return data;
        }

    }
}
